#pragma once

namespace vex {
    namespace core { namespace dispatch {
        struct any_out_dispatch {};
        struct any_in_dispatch {};

        template<class TContract> auto operator | (any_out_dispatch const&, TContract* p_contract)
            -> decltype(adl_as_any_from_out(p_contract))
        {
            return adl_as_any_from_out(p_contract);
        }

        template<class TContract> auto operator | (any_in_dispatch const&, TContract* p_contract)
            -> decltype(adl_as_any_from_in(p_contract))
        {
            return adl_as_any_from_in(p_contract);
        }
    }}

    /// <summary>
    /// Prepare conversion of a raw contract pointer returned as output parameter from a method
    /// to a smart handle of proper flavour. Use pipe <c>operator |</c> to pass the raw pointer.
    /// </summary>
    inline ::vex::core::dispatch::any_out_dispatch as_any_from_output() 
    {
        return ::vex::core::dispatch::any_out_dispatch();
    }

    /// <summary>
    /// Prepare conversion of a raw contract pointer received as input parameter in a method
    /// to a smart handle of proper flavour. Use pipe <c>operator |</c> to pass the raw pointer.
    /// </summary>
    inline ::vex::core::dispatch::any_in_dispatch as_any_from_input() 
    {
        return ::vex::core::dispatch::any_in_dispatch();
    }

    template<class TContract> inline auto as_any_from_out(TContract* p_handle) 
        -> decltype(adl_as_any_from_out(p_handle))
    {
        return adl_as_any_from_out(p_handle);
    }

    template<class TContract> inline auto as_any_from_in(TContract* p_handle) 
        -> decltype(adl_as_any_from_in(p_handle))
    {
        return adl_as_any_from_in(p_handle);
    }
}